/**
 * 通知服务层
 */
const notificationDao = require('../dao/notificationDao');
const { validatePagination, validateEnum } = require('../utils/validation');

/**
 * 获取用户通知列表服务
 * @param {number} userId - 用户ID
 * @param {Object} query - 查询参数
 * @returns {Object} 通知列表分页结果
 */
const getUserNotifications = async (userId, query) => {
  const { page, limit } = validatePagination(query);
  const { type, isRead } = query;

  // 验证通知类型
  if (type) {
    const typeValidation = validateEnum(type, ['system', 'course', 'game', 'daily', 'social'], '通知类型');
    if (!typeValidation.isValid) {
      throw new Error(typeValidation.message);
    }
  }

  const options = {
    user_id: userId,
    type,
    is_read: isRead !== undefined ? (isRead === 'true') : undefined,
    page,
    limit
  };

  const result = await notificationDao.getUserNotifications(options);

  const formattedList = result.notifications.map(notification => ({
    id: notification.id,
    title: notification.title,
    content: notification.content,
    type: notification.type,
    isRead: notification.is_read,
    data: notification.data,
    createdAt: notification.created_at,
    readAt: notification.read_at
  }));

  return {
    list: formattedList,
    total: result.total,
    page,
    limit,
    unreadCount: await getUnreadCount(userId)
  };
};

/**
 * 标记通知为已读服务
 * @param {number} userId - 用户ID
 * @param {number} notificationId - 通知ID
 * @returns {Object} 操作结果
 */
const markNotificationAsRead = async (userId, notificationId) => {
  // 检查通知是否存在且属于该用户
  const notification = await notificationDao.getNotificationById(notificationId);
  if (!notification) {
    throw new Error('通知不存在');
  }

  if (notification.user_id !== userId) {
    throw new Error('无权访问该通知');
  }

  if (notification.is_read) {
    throw new Error('通知已经是已读状态');
  }

  // 标记为已读
  await notificationDao.markAsRead(notificationId);

  return {
    success: true,
    message: '通知已标记为已读'
  };
};

/**
 * 批量标记通知为已读服务
 * @param {number} userId - 用户ID
 * @param {Array} notificationIds - 通知ID数组
 * @returns {Object} 操作结果
 */
const markNotificationsAsRead = async (userId, notificationIds) => {
  if (!Array.isArray(notificationIds) || notificationIds.length === 0) {
    throw new Error('通知ID列表不能为空');
  }

  // 验证所有通知都属于该用户
  const notifications = await notificationDao.getNotificationsByIds(notificationIds);
  const userNotifications = notifications.filter(n => n.user_id === userId);
  
  if (userNotifications.length !== notificationIds.length) {
    throw new Error('部分通知不存在或无权访问');
  }

  // 批量标记为已读
  const unreadIds = userNotifications.filter(n => !n.is_read).map(n => n.id);
  if (unreadIds.length > 0) {
    await notificationDao.markMultipleAsRead(unreadIds);
  }

  return {
    success: true,
    message: `已标记 ${unreadIds.length} 条通知为已读`,
    markedCount: unreadIds.length
  };
};

/**
 * 标记所有通知为已读服务
 * @param {number} userId - 用户ID
 * @returns {Object} 操作结果
 */
const markAllNotificationsAsRead = async (userId) => {
  const markedCount = await notificationDao.markAllAsReadForUser(userId);

  return {
    success: true,
    message: `已标记 ${markedCount} 条通知为已读`,
    markedCount
  };
};

/**
 * 删除通知服务
 * @param {number} userId - 用户ID
 * @param {number} notificationId - 通知ID
 * @returns {Object} 操作结果
 */
const deleteNotification = async (userId, notificationId) => {
  // 检查通知是否存在且属于该用户
  const notification = await notificationDao.getNotificationById(notificationId);
  if (!notification) {
    throw new Error('通知不存在');
  }

  if (notification.user_id !== userId) {
    throw new Error('无权删除该通知');
  }

  await notificationDao.deleteNotification(notificationId);

  return {
    success: true,
    message: '通知已删除'
  };
};

/**
 * 批量删除通知服务
 * @param {number} userId - 用户ID
 * @param {Array} notificationIds - 通知ID数组
 * @returns {Object} 操作结果
 */
const deleteNotifications = async (userId, notificationIds) => {
  if (!Array.isArray(notificationIds) || notificationIds.length === 0) {
    throw new Error('通知ID列表不能为空');
  }

  // 验证所有通知都属于该用户
  const notifications = await notificationDao.getNotificationsByIds(notificationIds);
  const userNotifications = notifications.filter(n => n.user_id === userId);
  
  if (userNotifications.length !== notificationIds.length) {
    throw new Error('部分通知不存在或无权访问');
  }

  const deletedCount = await notificationDao.deleteMultipleNotifications(notificationIds);

  return {
    success: true,
    message: `已删除 ${deletedCount} 条通知`,
    deletedCount
  };
};

/**
 * 获取通知统计服务
 * @param {number} userId - 用户ID
 * @returns {Object} 通知统计数据
 */
const getNotificationStats = async (userId) => {
  const stats = await notificationDao.getNotificationStats(userId);

  return {
    total: stats.total || 0,
    unread: stats.unread || 0,
    byType: {
      system: stats.system_count || 0,
      course: stats.course_count || 0,
      game: stats.game_count || 0,
      daily: stats.daily_count || 0,
      social: stats.social_count || 0
    }
  };
};

/**
 * 创建通知服务（系统内部使用）
 * @param {Object} notificationData - 通知数据
 * @returns {Object} 创建的通知
 */
const createNotification = async (notificationData) => {
  const { userId, title, content, type, data } = notificationData;

  // 验证通知类型
  const typeValidation = validateEnum(type, ['system', 'course', 'game', 'daily', 'social'], '通知类型');
  if (!typeValidation.isValid) {
    throw new Error(typeValidation.message);
  }

  const notification = await notificationDao.createNotification({
    user_id: userId,
    title,
    content,
    type,
    data: data || {},
    is_read: false
  });

  return {
    id: notification.id,
    title: notification.title,
    content: notification.content,
    type: notification.type,
    isRead: notification.is_read,
    data: notification.data,
    createdAt: notification.created_at
  };
};

/**
 * 批量创建通知服务（系统内部使用）
 * @param {Array} notificationsData - 通知数据数组
 * @returns {Object} 创建结果
 */
const createBulkNotifications = async (notificationsData) => {
  if (!Array.isArray(notificationsData) || notificationsData.length === 0) {
    throw new Error('通知数据不能为空');
  }

  // 验证所有通知数据
  for (const data of notificationsData) {
    const typeValidation = validateEnum(data.type, ['system', 'course', 'game', 'daily', 'social'], '通知类型');
    if (!typeValidation.isValid) {
      throw new Error(`通知类型验证失败: ${typeValidation.message}`);
    }
  }

  const createdCount = await notificationDao.createBulkNotifications(notificationsData);

  return {
    success: true,
    message: `已创建 ${createdCount} 条通知`,
    createdCount
  };
};

/**
 * 获取未读通知数量（辅助函数）
 * @param {number} userId - 用户ID
 * @returns {number} 未读通知数量
 */
const getUnreadCount = async (userId) => {
  const count = await notificationDao.getUnreadCount(userId);
  return count || 0;
};

/**
 * 发送系统通知（辅助函数）
 * @param {number} userId - 用户ID
 * @param {string} title - 通知标题
 * @param {string} content - 通知内容
 * @param {Object} data - 附加数据
 */
const sendSystemNotification = async (userId, title, content, data = {}) => {
  return await createNotification({
    userId,
    title,
    content,
    type: 'system',
    data
  });
};

/**
 * 发送课程通知（辅助函数）
 * @param {number} userId - 用户ID
 * @param {string} title - 通知标题
 * @param {string} content - 通知内容
 * @param {Object} data - 附加数据
 */
const sendCourseNotification = async (userId, title, content, data = {}) => {
  return await createNotification({
    userId,
    title,
    content,
    type: 'course',
    data
  });
};

module.exports = {
  getUserNotifications,
  markNotificationAsRead,
  markNotificationsAsRead,
  markAllNotificationsAsRead,
  deleteNotification,
  deleteNotifications,
  getNotificationStats,
  createNotification,
  createBulkNotifications,
  sendSystemNotification,
  sendCourseNotification
};
